package com.zkh.myframe.server.tomcat.websocket;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;

import com.zkh.myutils.utils.Assert;

/**
 * WebSocket默认会话池
 * @author zkh
 */
public class WebSocketDefaultSessionPools implements SessionPool {
	//统计在线连接数。其中key为分支编号
	private Map<String, Integer> onlineCountMap = new ConcurrentHashMap<>();
	//所有连接的集合。其中key为分支编号
	private Map<String, Set<WebSocketCore>> webSocketSet = new ConcurrentHashMap<>();
	//所有用户对应的连接。。其中外层key为分支编号，内层key为用户标识。
	private Map<String, Map<String, WebSocketCore>> webSocketMap = new ConcurrentHashMap<>();
	
	//空Map和Set
	private Map<String, WebSocketCore> emptyMap = new ConcurrentHashMap<>();
	
	/**
	 * 获取指定分支连接数
	 * @param branchId 分支编号
	 */
	public int getOnlineCount(String branchId) {
		return Assert.getIfNotNull(onlineCountMap.get(branchId), v->v, 0);
	}

	/**
	 * 指定分支连接数加1
	 * @param branchId 分支编号
	 */
	public int addOnlineCount(String branchId) {
		//对分支加锁，不同分支可以并行
		synchronized (branchId.intern()) {
			//获取现在连接数，用来返回
			Integer c = Assert.getIfNotNull(onlineCountMap.get(branchId), v->v+1, 1);
			//存在，加1，否则设置值为1
			onlineCountMap.put(branchId, c);
			//返回连接数
			return c;
		}
	}
	
	/**
	 * 指定分支连接数减1
	 * @param branchId 分支编号
	 */
	public int subtractOnlineCount(String branchId) {
		//对分支加锁，不同分支可以并行
		synchronized (branchId.intern()) {
			//获取现在连接数，用来返回
			int c = onlineCountMap.get(branchId) - 1;
			//存在，加1，否则设置值为1
			onlineCountMap.put(branchId, c);
			//返回连接数
			return c;
		}
	}

	/**
	 * 保存WebSocket连接
	 * @param branchId 分支编号
	 * @param userKey 用户标识
	 * @param webSocketCore WebSocket连接
	 */
	public void saveSocket(String branchId, String userKey, WebSocketCore webSocketCore) {
		//对分支加锁，不同分支可以并行
		synchronized (branchId.intern()) {
			//获取集合
			Set<WebSocketCore> set = webSocketSet.get(branchId);
			Map<String, WebSocketCore> map = webSocketMap.get(branchId);
			//不存在，则创建
			if(set==null) webSocketSet.put(branchId, set=new CopyOnWriteArraySet<>());
			if(map==null) webSocketMap.put(branchId, map = new ConcurrentHashMap<>());
			//获取已存在会话
			WebSocketCore exist = map.get(userKey);
			//会话已存在，则先关闭已存在会话
			if(exist!=null) {
				//移除会话并关闭
				removeSocket(branchId, userKey, exist).close();
			}
			//保存
			set.add(webSocketCore);
			map.put(userKey, webSocketCore);
		}
	}
	
	/**
	 * 移除WebSocket连接
	 * @param branchId 分支编号
	 * @param userKey 用户标识
	 * @param webSocketCore WebSocket连接
	 * @return 返回被移除的会话
	 */
	public WebSocketCore removeSocket(String branchId, String userKey, WebSocketCore webSocketCore) {
		//对分支加锁，不同分支可以并行
		synchronized (branchId.intern()) {
			//移除会话
			webSocketSet.get(branchId).remove(webSocketCore);
			return webSocketMap.get(branchId).remove(userKey);
		}
	}
	
	/**
	 * 获取一个WebSocket连接。如果返回对象为null，说明用户不在线
	 * @param branchId 分支编号
	 * @param userKey 用户标识
	 */
	public WebSocketCore getWebSocketSession(String branchId, String userKey) {
		return webSocketMap.getOrDefault(branchId, emptyMap).get(userKey);
	}
	
	/**
	 * 获取多个WebSocket连接。如果返回列表的项为null，说明用户不在线
	 * @param branchId 分支编号
	 * @param userKeyList 用户标识列表
	 * @param offlineUserList 离线用户列表。如果不需要获取离线用户，直接传null即可
	 */
	public List<WebSocketCore> getWebSocketSessions(String branchId, List<String> userKeyList, List<String> offlineUserList){
		//最终容器
		List<WebSocketCore> ctnList = new ArrayList<>();
		//离线用户列表
		(offlineUserList==null ? offlineUserList=new ArrayList<String>() : offlineUserList).addAll(userKeyList);
		//会话列表
		Map<String, WebSocketCore> map = webSocketMap.getOrDefault(branchId, emptyMap);
		//开始遍历
		for(Entry<String, WebSocketCore> entry: map.entrySet()) {
			//获取key索引
			int keyIndex = offlineUserList.indexOf(entry.getKey());
			//存在
			if(keyIndex>-1) {
				ctnList.add(entry.getValue());
				offlineUserList.remove(keyIndex);
			}
			//已获取完，退出遍历
			if(offlineUserList.isEmpty()) {
				break;
			}
		}
		//返回对比数据
		return ctnList;
	}
}
